home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 25 / AACD 25.iso / AACD / Utilities / BasiliskII / src / AmigaOS / extfs_amiga.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-31  |  10.8 KB  |  386 lines

  1. /*
  2.  *  extfs_amiga.cpp - MacOS file system for access native file system access, AmigaOS specific stuff
  3.  *
  4.  *  Basilisk II (C) 1997-2001 Christian Bauer
  5.  *
  6.  *  This program is free software; you can redistribute it and/or modify
  7.  *  it under the terms of the GNU General Public License as published by
  8.  *  the Free Software Foundation; either version 2 of the License, or
  9.  *  (at your option) any later version.
  10.  *
  11.  *  This program is distributed in the hope that it will be useful,
  12.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *  GNU General Public License for more details.
  15.  *
  16.  *  You should have received a copy of the GNU General Public License
  17.  *  along with this program; if not, write to the Free Software
  18.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  */
  20.  
  21. #include <exec/types.h>
  22. #include <proto/dos.h>
  23.  
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30. #include <dirent.h>
  31. #include <errno.h>
  32.  
  33. #include "sysdeps.h"
  34. #include "extfs.h"
  35. #include "extfs_defs.h"
  36.  
  37. #define DEBUG 0
  38. #include "debug.h"
  39.  
  40.  
  41. // Default Finder flags
  42. const uint16 DEFAULT_FINDER_FLAGS = kHasBeenInited;
  43.  
  44.  
  45. /*
  46.  *  Initialization
  47.  */
  48.  
  49. void extfs_init(void)
  50. {
  51. }
  52.  
  53.  
  54. /*
  55.  *  Deinitialization
  56.  */
  57.  
  58. void extfs_exit(void)
  59. {
  60. }
  61.  
  62.  
  63. /*
  64.  *  Add component to path name
  65.  */
  66.  
  67. void add_path_component(char *path, const char *component)
  68. {
  69.     AddPart(path, (char *)component, MAX_PATH_LENGTH);
  70. }
  71.  
  72.  
  73. /*
  74.  *  Finder info and resource forks are kept in helper files
  75.  *
  76.  *  Finder info:
  77.  *    /path/.finf/file
  78.  *  Resource fork:
  79.  *    /path/.rsrc/file
  80.  *
  81.  *  The .finf files store a FInfo/DInfo, followed by a FXInfo/DXInfo
  82.  *  (16+16 bytes)
  83.  */
  84.  
  85. static void make_helper_path(const char *src, char *dest, const char *add, bool only_dir = false)
  86. {
  87.     dest[0] = 0;
  88.  
  89.     // Get pointer to last component of path
  90.     const char *last_part = FilePart((char *)src);
  91.  
  92.     // Copy everything before
  93.     strncpy(dest, src, last_part-src);
  94.     dest[last_part-src] = 0;
  95.  
  96.     // Add additional component
  97.     AddPart(dest, (char *)add, MAX_PATH_LENGTH);
  98.  
  99.     // Add last component
  100.     if (!only_dir)
  101.         AddPart(dest, (char *)last_part, MAX_PATH_LENGTH);
  102. }
  103.  
  104. static int create_helper_dir(const char *path, const char *add)
  105. {
  106.     char helper_dir[MAX_PATH_LENGTH];
  107.     make_helper_path(path, helper_dir, add, true);
  108.     if (helper_dir[strlen(helper_dir) - 1] == '/')    // Remove trailing "/"
  109.         helper_dir[strlen(helper_dir) - 1] = 0;
  110.     return mkdir(helper_dir, 0777);
  111. }
  112.  
  113. static int open_helper(const char *path, const char *add, int flag)
  114. {
  115.     char helper_path[MAX_PATH_LENGTH];
  116.     make_helper_path(path, helper_path, add);
  117.  
  118.     if ((flag & O_ACCMODE) == O_RDWR || (flag & O_ACCMODE) == O_WRONLY)
  119.         flag |= O_CREAT;
  120.     int fd = open(helper_path, flag, 0666);
  121.     if (fd < 0) {
  122.         if (errno == ENOENT && (flag & O_CREAT)) {
  123.             // One path component was missing, probably the helper
  124.             // directory. Try to create it and re-open the file.
  125.             int ret = create_helper_dir(path, add);
  126.             if (ret < 0)
  127.                 return ret;
  128.             fd = open(helper_path, flag, 0666);
  129.         }
  130.     }
  131.     return fd;
  132. }
  133.  
  134. static int open_finf(const char *path, int flag)
  135. {
  136.     return open_helper(path, ".finf/", flag);
  137. }
  138.  
  139. static int open_rsrc(const char *path, int flag)
  140. {
  141.     return open_helper(path, ".rsrc/", flag);
  142. }
  143.  
  144.  
  145. /*
  146.  *  Get/set finder type/creator for file specified by full path
  147.  */
  148.  
  149. struct ext2type {
  150.     const char *ext;
  151.     uint32 type;
  152.     uint32 creator;
  153. };
  154.  
  155. static const ext2type e2t_translation[] = {
  156.     {".z", FOURCC('Z','I','V','M'), FOURCC('L','Z','I','V')},
  157.     {".gz", FOURCC('G','z','i','p'), FOURCC('G','z','i','p')},
  158.     {".hqx", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
  159.     {".bin", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
  160.     {".pdf", FOURCC('P','D','F',' '), FOURCC('C','A','R','O')},
  161.     {".ps", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
  162.     {".sit", FOURCC('S','I','T','!'), FOURCC('S','I','T','x')},
  163.     {".tar", FOURCC('T','A','R','F'), FOURCC('T','A','R',' ')},
  164.     {".uu", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
  165.     {".uue", FOURCC('T','E','X','T'), FOURCC('S','I','T','x')},
  166.     {".zip", FOURCC('Z','I','P',' '), FOURCC('Z','I','P',' ')},
  167.     {".8svx", FOURCC('8','S','V','X'), FOURCC('S','N','D','M')},
  168.     {".aifc", FOURCC('A','I','F','C'), FOURCC('T','V','O','D')},
  169.     {".aiff", FOURCC('A','I','F','F'), FOURCC('T','V','O','D')},
  170.     {".au", FOURCC('U','L','A','W'), FOURCC('T','V','O','D')},
  171.     {".mid", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
  172.     {".midi", FOURCC('M','I','D','I'), FOURCC('T','V','O','D')},
  173.     {".mp2", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
  174.     {".mp3", FOURCC('M','P','G',' '), FOURCC('T','V','O','D')},
  175.     {".wav", FOURCC('W','A','V','E'), FOURCC('T','V','O','D')},
  176.     {".bmp", FOURCC('B','M','P','f'), FOURCC('o','g','l','e')},
  177.     {".gif", FOURCC('G','I','F','f'), FOURCC('o','g','l','e')},
  178.     {".lbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
  179.     {".ilbm", FOURCC('I','L','B','M'), FOURCC('G','K','O','N')},
  180.     {".jpg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
  181.     {".jpeg", FOURCC('J','P','E','G'), FOURCC('o','g','l','e')},
  182.     {".pict", FOURCC('P','I','C','T'), FOURCC('o','g','l','e')},
  183.     {".png", FOURCC('P','N','G','f'), FOURCC('o','g','l','e')},
  184.     {".sgi", FOURCC('.','S','G','I'), FOURCC('o','g','l','e')},
  185.     {".tga", FOURCC('T','P','I','C'), FOURCC('o','g','l','e')},
  186.     {".tif", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
  187.     {".tiff", FOURCC('T','I','F','F'), FOURCC('o','g','l','e')},
  188.     {".htm", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
  189.     {".html", FOURCC('T','E','X','T'), FOURCC('M','O','S','S')},
  190.     {".txt", FOURCC('T','E','X','T'), FOURCC('t','t','x','t')},
  191.     {".rtf", FOURCC('T','E','X','T'), FOURCC('M','S','W','D')},
  192.     {".c", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  193.     {".cc", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  194.     {".cpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  195.     {".cxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  196.     {".h", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  197.     {".hh", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  198.     {".hpp", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  199.     {".hxx", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  200.     {".s", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  201.     {".i", FOURCC('T','E','X','T'), FOURCC('R','*','c','h')},
  202.     {".mpg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
  203.     {".mpeg", FOURCC('M','P','E','G'), FOURCC('T','V','O','D')},
  204.     {".mov", FOURCC('M','o','o','V'), FOURCC('T','V','O','D')},
  205.     {".fli", FOURCC('F','L','I',' '), FOURCC('T','V','O','D')},
  206.     {".avi", FOURCC('V','f','W',' '), FOURCC('T','V','O','D')},
  207.     {".qxd", FOURCC('X','D','O','C'), FOURCC('X','P','R','3')},
  208.     {".hfv", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
  209.     {".dsk", FOURCC('D','D','i','m'), FOURCC('d','d','s','k')},
  210.     {".img", FOURCC('r','o','h','d'), FOURCC('d','d','s','k')},
  211.     {NULL, 0, 0}    // End marker
  212. };
  213.  
  214. void get_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
  215. {
  216.     // Set default finder info
  217.     Mac_memset(finfo, 0, SIZEOF_FInfo);
  218.     if (fxinfo)
  219.         Mac_memset(fxinfo, 0, SIZEOF_FXInfo);
  220.     WriteMacInt16(finfo + fdFlags, DEFAULT_FINDER_FLAGS);
  221.     WriteMacInt32(finfo + fdLocation, (uint32)-1);
  222.  
  223.     // Read Finder info file
  224.     int fd = open_finf(path, O_RDONLY);
  225.     if (fd >= 0) {
  226.         ssize_t actual = read(fd, Mac2HostAddr(finfo), SIZEOF_FInfo);
  227.         if (fxinfo)
  228.             actual += read(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo);
  229.         close(fd);
  230.         if (actual >= SIZEOF_FInfo)
  231.             return;
  232.     }
  233.  
  234.     // No Finder info file, translate file name extension to MacOS type/creator
  235.     if (!is_dir) {
  236.         int path_len = strlen(path);
  237.         for (int i=0; e2t_translation[i].ext; i++) {
  238.             int ext_len = strlen(e2t_translation[i].ext);
  239.             if (path_len < ext_len)
  240.                 continue;
  241.             if (!strcasecmp(path + path_len - ext_len, e2t_translation[i].ext)) {
  242.                 WriteMacInt32(finfo + fdType, e2t_translation[i].type);
  243.                 WriteMacInt32(finfo + fdCreator, e2t_translation[i].creator);
  244.                 break;
  245.             }
  246.         }
  247.     }
  248. }
  249.  
  250. void set_finfo(const char *path, uint32 finfo, uint32 fxinfo, bool is_dir)
  251. {
  252.     // Open Finder info file
  253.     int fd = open_finf(path, O_RDWR);
  254.     if (fd < 0)
  255.         return;
  256.  
  257.     // Write file
  258.     write(fd, Mac2HostAddr(finfo), SIZEOF_FInfo);
  259.     if (fxinfo)
  260.         write(fd, Mac2HostAddr(fxinfo), SIZEOF_FXInfo);
  261.     close(fd);
  262. }
  263.  
  264.  
  265. /*
  266.  *  Resource fork emulation functions
  267.  */
  268.  
  269. uint32 get_rfork_size(const char *path)
  270. {
  271.     // Open resource file
  272.     int fd = open_rsrc(path, O_RDONLY);
  273.     if (fd < 0)
  274.         return 0;
  275.  
  276.     // Get size
  277.     off_t size = lseek(fd, 0, SEEK_END);
  278.     
  279.     // Close file and return size
  280.     close(fd);
  281.     return size < 0 ? 0 : size;
  282. }
  283.  
  284. int open_rfork(const char *path, int flag)
  285. {
  286.     return open_rsrc(path, flag);
  287. }
  288.  
  289. void close_rfork(const char *path, int fd)
  290. {
  291.     close(fd);
  292. }
  293.  
  294.  
  295. /*
  296.  *  Read "length" bytes from file to "buffer",
  297.  *  returns number of bytes read (or -1 on error)
  298.  */
  299.  
  300. ssize_t extfs_read(int fd, void *buffer, size_t length)
  301. {
  302.     return read(fd, buffer, length);
  303. }
  304.  
  305.  
  306. /*
  307.  *  Write "length" bytes from "buffer" to file,
  308.  *  returns number of bytes written (or -1 on error)
  309.  */
  310.  
  311. ssize_t extfs_write(int fd, void *buffer, size_t length)
  312. {
  313.     return write(fd, buffer, length);
  314. }
  315.  
  316.  
  317. /*
  318.  *  Remove file/directory (and associated helper files),
  319.  *  returns false on error (and sets errno)
  320.  */
  321.  
  322. bool extfs_remove(const char *path)
  323. {
  324.     // Remove helpers first, don't complain if this fails
  325.     char helper_path[MAX_PATH_LENGTH];
  326.     make_helper_path(path, helper_path, ".finf/", false);
  327.     remove(helper_path);
  328.     make_helper_path(path, helper_path, ".rsrc/", false);
  329.     remove(helper_path);
  330.  
  331.     // Now remove file or directory (and helper directories in the directory)
  332.     if (remove(path) < 0) {
  333.         if (errno == EISDIR || errno == ENOTEMPTY) {
  334.             helper_path[0] = 0;
  335.             strncpy(helper_path, path, MAX_PATH_LENGTH-1);
  336.             add_path_component(helper_path, ".finf");
  337.             rmdir(helper_path);
  338.             helper_path[0] = 0;
  339.             strncpy(helper_path, path, MAX_PATH_LENGTH-1);
  340.             add_path_component(helper_path, ".rsrc");
  341.             rmdir(helper_path);
  342.             return rmdir(path) == 0;
  343.         } else
  344.             return false;
  345.     }
  346.     return true;
  347. }
  348.  
  349.  
  350. /*
  351.  *  Rename/move file/directory (and associated helper files),
  352.  *  returns false on error (and sets errno)
  353.  */
  354.  
  355. bool extfs_rename(const char *old_path, const char *new_path)
  356. {
  357.     // Rename helpers first, don't complain if this fails
  358.     char old_helper_path[MAX_PATH_LENGTH], new_helper_path[MAX_PATH_LENGTH];
  359.     make_helper_path(old_path, old_helper_path, ".finf/", false);
  360.     make_helper_path(new_path, new_helper_path, ".finf/", false);
  361.     create_helper_dir(new_path, ".finf/");
  362.     rename(old_helper_path, new_helper_path);
  363.     make_helper_path(old_path, old_helper_path, ".rsrc/", false);
  364.     make_helper_path(new_path, new_helper_path, ".rsrc/", false);
  365.     create_helper_dir(new_path, ".rsrc/");
  366.     rename(old_helper_path, new_helper_path);
  367.  
  368.     // Now rename file
  369.     return rename(old_path, new_path) == 0;
  370. }
  371.  
  372.  
  373. /*
  374.  *  ftruncate() is missing from libnix
  375.  */
  376.  
  377. extern unsigned long *__stdfiledes;
  378.  
  379. int ftruncate(int fd, off_t size)
  380. {
  381.     if (SetFileSize(__stdfiledes[fd], size, OFFSET_BEGINNING) < 0)
  382.         return -1;
  383.     else
  384.         return 0;
  385. }
  386.